package com.joshua.spring.integration;

import com.google.common.collect.Lists;
import com.joshua.spring.entity.dto.UserInfoDTO;
import com.joshua.spring.entity.em.ResponseEnum;
import com.joshua.spring.integration.authenticator.IntegrationAuthenticator;
import com.joshua.spring.integration.exception.IntegrationAuthenticationServiceException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;

import java.util.List;

import static com.joshua.spring.entity.constant.GrantTypeConstants.PWD;
import static com.joshua.spring.entity.constant.GrantTypeConstants.REFRESH;
import static org.springframework.security.oauth2.common.util.OAuth2Utils.GRANT_TYPE;

/**
 * com.joshua.spring.business.configuration -- UserDetailServiceImpl
 * description: Spring security {@link UserDetailsService} 实现类
 *
 * @author <a href="mailto:joshualwork@163.com">joshua_liu</a>
 * @date 2020/1/3 15:20
 */
@Component
@Slf4j
public class IntegrationUserDetailServiceImpl implements UserDetailsService {

    @Autowired
    private List<IntegrationAuthenticator> authenticators;

    @Autowired
    private PasswordEncoder passwordEncoder;

    /**
     * description: 注意，这里return的user中的password
     * 必须要和BCryptPasswordEncoder.encode(登录时输入的密码)一样
     * 才会通过校验
     *
     * @param username
     * @return {@link UserDetails}
     * @throws {@link UsernameNotFoundException} 用户不存在
     * @author <a href="mailto:joshualwork@163.com">joshua_liu</a>
     * @date 2020/1/3 17:24
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        IntegrationAuthentication integrationAuthentication = IntegrationAuthenticationContext.get();
        if (integrationAuthentication == null) {
            integrationAuthentication = new IntegrationAuthentication();
        }
        String encodePassword = passwordEncoder.encode(integrationAuthentication.getAuthParameter(PWD));
        if (!REFRESH.equals(integrationAuthentication.getAuthParameter(GRANT_TYPE))) {
            UserInfoDTO dto = this.authenticate(integrationAuthentication);
            if (dto == null) {
                throw new IntegrationAuthenticationServiceException(ResponseEnum.USER_NOT_FOUND);
            }
            username = dto.getUsername();
        }
        // 默认所有用户拥有 USER 权限
        List<GrantedAuthority> grantedAuthorities = Lists.newArrayList();
        GrantedAuthority grantedAuthority = new SimpleGrantedAuthority("USER");
        grantedAuthorities.add(grantedAuthority);
        return new User(username, encodePassword, grantedAuthorities);
    }

    private UserInfoDTO authenticate(IntegrationAuthentication integrationAuthentication) {
        if (this.authenticators != null) {
            for (IntegrationAuthenticator authenticator : authenticators) {
                if (authenticator.support(integrationAuthentication)) {
                    return authenticator.authenticate(integrationAuthentication);
                }
            }
        }
        return null;
    }
}
